package util;

import ch.qos.logback.core.db.dialect.DBUtil;
import entity.ArticleVo;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class POIUtil {
    private static Map<String,Map<String,Object>> orderMap =null;
    public ArticleVo world(MultipartFile file){
        orderMap =new HashMap<String, Map<String,Object>>();
        InputStream is = null;
        XWPFDocument createDoc = new XWPFDocument();
        ArticleVo articleVo = new ArticleVo();
        try {
            is = file.getInputStream();
            XWPFDocument doc = new XWPFDocument (is);
            List<XWPFParagraph> paras=doc.getParagraphs();
            System.out.println(doc.getStyles());
            for (XWPFParagraph para : paras) {
                String titleLvl = getTitleLvl(doc,para);
                String num = getOrderCode(titleLvl);
                String strs = null;
                if(!"0".equals(titleLvl)&&!"1".equals(titleLvl)) {
                    strs = num.split("\\.")[0];
                }
                        System.out.println("getOrderCode:"+num);
                if("0".equals(titleLvl)){
                    articleVo.setName(para.getParagraphText());
                }else if("1".equals(titleLvl)){
                    if(articleVo.getTitle()!=null){
                        articleVo.getTitle().add(para.getParagraphText());
                    }else{
                        List<String> stringList = new ArrayList<>();
                        stringList.add(para.getParagraphText());
                        articleVo.setTitle(stringList);
                    }


                }else if("2".equals(titleLvl)){
                    if(articleVo.getContent()!=null){
                        if(articleVo.getContent().get(Integer.valueOf(strs))!=null){
                            articleVo.getContent().put(Integer.valueOf(strs), articleVo.getContent().get(Integer.valueOf(strs)) + "\n" + para.getParagraphText());

                        }else {
                            articleVo.getContent().put(Integer.valueOf(strs), para.getParagraphText());

                        }
                    }else {
                        Map<Integer,String> map1 = new HashMap<>();
                        map1.put(Integer.valueOf(strs), para.getParagraphText());
                        articleVo.setContent(map1);
                    }

                }else if("3".equals(titleLvl)){
                    if(articleVo.getHandout()!=null){
                        if( articleVo.getHandout().get(Integer.valueOf(strs))!=null) {
                            articleVo.getHandout().put(Integer.valueOf(strs), articleVo.getHandout().get(Integer.valueOf(strs)) + "\n" + para.getParagraphText());
                        }else {
                            articleVo.getHandout().put(Integer.valueOf(strs), para.getParagraphText());
                        }
                    }else {
                        Map<Integer,String> map1 = new HashMap<>();
                        map1.put(Integer.valueOf(strs), para.getParagraphText());
                        articleVo.setHandout(map1);
                    }
                }else if(!"8".equals(titleLvl)){
                         System.out.println(titleLvl+"===="+para.getParagraphText());
                     }
            }

        } catch (IOException e) {
            e.printStackTrace();

        }catch (Exception e){
            e.printStackTrace();
            return null;
        }finally{
            try {
                if(null!=is){
                    is.close();
                }
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
        return articleVo;
    }
     /**
       * Word中的大纲级别，可以通过getPPr().getOutlineLvl()直接提取，但需要注意，Word中段落级别，通过如下三种方式定义：
       *  1、直接对段落进行定义；
       *  2、对段落的样式进行定义；
       *  3、对段落样式的基础样式进行定义。
       *  因此，在通过“getPPr().getOutlineLvl()”提取时，需要依次在如上三处读取。
       * @param doc
       * @param para
       * @return
       */
             private static String getTitleLvl(XWPFDocument doc, XWPFParagraph para) {
                 String titleLvl = "";
                 try {
                         //判断该段落是否设置了大纲级别
                         if (para.getCTP().getPPr().getOutlineLvl() != null) {
                                 // System.out.println("getCTP()");
                 //              System.out.println(para.getParagraphText());
                 //              System.out.println(para.getCTP().getPPr().getOutlineLvl().getVal());

                                 return String.valueOf(para.getCTP().getPPr().getOutlineLvl().getVal());
                             }
                     } catch (Exception e) {

                     }

                 try {
                         //判断该段落的样式是否设置了大纲级别
                         if (doc.getStyles().getStyle(para.getStyle()).getCTStyle().getPPr().getOutlineLvl() != null) {

                                 // System.out.println("getStyle");
                 //              System.out.println(para.getParagraphText());
                 //              System.out.println(doc.getStyles().getStyle(para.getStyle()).getCTStyle().getPPr().getOutlineLvl().getVal());

                                 return String.valueOf(doc.getStyles().getStyle(para.getStyle()).getCTStyle().getPPr().getOutlineLvl().getVal());
                             }
                     } catch (Exception e) {

                     }

                 try {
                         //判断该段落的样式的基础样式是否设置了大纲级别
                         if (doc.getStyles().getStyle(doc.getStyles().getStyle(para.getStyle()).getCTStyle().getBasedOn().getVal())
                                 .getCTStyle().getPPr().getOutlineLvl() != null) {
                                 // System.out.println("getBasedOn");
                 //              System.out.println(para.getParagraphText());
                                 String styleName = doc.getStyles().getStyle(para.getStyle()).getCTStyle().getBasedOn().getVal();
                 //              System.out.println(doc.getStyles().getStyle(styleName).getCTStyle().getPPr().getOutlineLvl().getVal());

                                 return String.valueOf(doc.getStyles().getStyle(styleName).getCTStyle().getPPr().getOutlineLvl().getVal());
                             }
                     } catch (Exception e) {

                     }

                 try {
                         if(para.getStyleID()!=null){
                                 return para.getStyleID();
                             }
                     } catch (Exception e) {

                     }

                 return titleLvl;
             }

             /**
       * 增加自定义标题样式。这里用的是stackoverflow的源码
       *
       * @param docxDocument 目标文档
       * @param strStyleId 样式名称
       * @param headingLevel 样式级别
       */
             private static void addCustomHeadingStyle(XWPFDocument docxDocument, String strStyleId, int headingLevel) {

                 strStyleId = String.valueOf(Integer.parseInt(strStyleId)+1);
                 CTStyle ctStyle = CTStyle.Factory.newInstance();
                 ctStyle.setStyleId(strStyleId);

                 CTString styleName = CTString.Factory.newInstance();
                 styleName.setVal(strStyleId);
                 ctStyle.setName(styleName);

                 CTDecimalNumber indentNumber = CTDecimalNumber.Factory.newInstance();
                 indentNumber.setVal(BigInteger.valueOf(headingLevel));

                 // lower number > style is more prominent in the formats bar
                 ctStyle.setUiPriority(indentNumber);

                 CTOnOff onoffnull = CTOnOff.Factory.newInstance();
                 ctStyle.setUnhideWhenUsed(onoffnull);

                 // style shows up in the formats bar
                 ctStyle.setQFormat(onoffnull);

                 // style defines a heading of the given level
                 CTPPr ppr = CTPPr.Factory.newInstance();
                 ppr.setOutlineLvl(indentNumber);
                 ctStyle.setPPr(ppr);

                 XWPFStyle style = new XWPFStyle(ctStyle);

                 // is a null op if already defined
                 XWPFStyles styles = docxDocument.createStyles();

                 style.setType(STStyleType.PARAGRAPH);
                 styles.addStyle(style);

             }
     /**
       * 获取标题编号
       * @param titleLvl
       * @return
       */
             private static String getOrderCode(String titleLvl) {

                 String order = "";

                 if("0".equals(titleLvl)||Integer.parseInt(titleLvl)==8){//文档标题||正文
                         return "";
                     }else if(Integer.parseInt(titleLvl)>0&&Integer.parseInt(titleLvl)<8){//段落标题

                         //设置最高级别标题
                         Map<String,Object> maxTitleMap = orderMap.get("maxTitleLvlMap");
                         if(null==maxTitleMap){//没有，表示第一次进来
                                 //最高级别标题赋值
                                 maxTitleMap = new HashMap<String, Object>();
                                 maxTitleMap.put("lvl", titleLvl);
                                 orderMap.put("maxTitleLvlMap", maxTitleMap);
                             }else{
                                 String maxTitleLvl = maxTitleMap.get("lvl")+"";//最上层标题级别(0,1,2,3)
                                 if(Integer.parseInt(titleLvl)<Integer.parseInt(maxTitleLvl)){//当前标题级别更高
                                         maxTitleMap.put("lvl", titleLvl);//设置最高级别标题
                                         orderMap.put("maxTitleLvlMap", maxTitleMap);
                                     }
                             }

                         //查父节点标题
                         int parentTitleLvl = Integer.parseInt(titleLvl)-1;//父节点标题级别
                         Map<String,Object> cMap = orderMap.get(titleLvl);//当前节点信息
                         Map<String,Object> pMap = orderMap.get(parentTitleLvl+"");//父节点信息

                         if(0==parentTitleLvl){//父节点为文档标题，表明当前节点为1级标题
                                 int count= 0;
                                 //最上层标题，没有父节点信息
                                 if(null==cMap){//没有当前节点信息
                                         cMap = new HashMap<String, Object>();
                                     }else{
                                         count = Integer.parseInt(String.valueOf(cMap.get("cCount")));//当前序个数
                                     }
                                 count++;
                                 order = count+"";
                                 cMap.put("cOrder", order);//当前序
                                 cMap.put("cCount", count);//当前序个数
                                 orderMap.put(titleLvl, cMap);

                             }else{//父节点为非文档标题
                                 int count= 0;
                                 //如果没有相邻的父节点信息，当前标题级别自动升级
                                 if(null==pMap){
                                         return getOrderCode(String.valueOf(parentTitleLvl));
                                     }else{
                                         String pOrder = String.valueOf(pMap.get("cOrder"));//父节点序
                                         if(null==cMap){//没有当前节点信息
                                                 cMap = new HashMap<String, Object>();
                                             }else{
                                                 count = Integer.parseInt(String.valueOf(cMap.get("cCount")));//当前序个数
                                             }
                                         count++;
                                         order = pOrder+"."+count;//当前序编号
                                         cMap.put("cOrder", order);//当前序
                                         cMap.put("cCount", count);//当前序个数
                                         orderMap.put(titleLvl, cMap);
                                     }
                             }

                         //字节点标题计数清零
                         int childTitleLvl = Integer.parseInt(titleLvl)+1;//子节点标题级别
                         Map<String,Object> cdMap = orderMap.get(childTitleLvl+"");//
                         if(null!=cdMap){
                                 cdMap.put("cCount", 0);//子节点序个数
                                 orderMap.get(childTitleLvl+"").put("cCount", 0);
                             }
                     }
                 return order;
             }

             public static void main(String[] args) {
                 orderMap =new HashMap<String, Map<String,Object>>();
                 InputStream is = null;
                 XWPFDocument doc=null;
                 OutputStream out=null;
                 String[] title= new String [276];
                 String[] concent= new String [276];
                 String[] type= new String [276];
                 int i=0;
                 try {
                         XWPFDocument createDoc = new XWPFDocument();

                         is = new FileInputStream("E:/word/a.docx");
                         doc = new XWPFDocument(is);
                         //获取段落
                         List<XWPFParagraph> paras=doc.getParagraphs();

                         for (XWPFParagraph para : paras){
                               //System.out.println("段落级别"+para.getStyleID());//段落级别
                               //System.out.print(para.getParagraphText());//段落内容
                               String titleLvl = getTitleLvl(doc,para);

                                if(!("0").equals(titleLvl)){
                                    System.out.println("取段落级别:"+titleLvl);
                                    System.out.println("getOrderCode:"+getOrderCode(titleLvl));
                                }
                               //获取段落级别
                               if("a5".equals(titleLvl)||"HTML".equals(titleLvl)||"".equals(titleLvl)||null==titleLvl){
                                       titleLvl = "8";
                                   }
                             //System.out.println("取段落级别"+titleLvl+"-----");//0,1,2
                              if(!"8".equals(titleLvl)){
                                     //System.out.println(titleLvl+"===="+para.getParagraphText());

                                     if("3".equals(titleLvl)) {

                                             if(concent[i]!=null)
                                                 concent[i]=concent[i]+para.getParagraphText();
                                             else
                                             concent[i]=para.getParagraphText();
                                             //System.out.println(concent[i]);
                                         }
                                     if("2".equals(titleLvl)) {
                                             i++;
                                             title[i]=para.getParagraphText();
                                             //System.out.println(title[i]);
                                         }
                                     if("1".equals(titleLvl)) {
                                             i++;
                                             type[i]=para.getParagraphText();
                                             //System.out.println(title[i]);
                                         }
                                 }


                             }
                     System.out.println(title.toString());
                     System.out.println(concent.toString());
                     System.out.println(type.toString());
                     } catch (Exception e) {
                         e.printStackTrace();
                     } finally{
                         try {
                                 if(null!=out){
                                         out.close();
                                     }
                                 if(null!=is){
                                         is.close();
                                     }
                             }catch (IOException e) {
                                 e.printStackTrace();
                             }
                     }
             }
}
